package com.ikun.kunaicode.core.saver;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.ikun.kunaicode.constant.AppConstant;
import com.ikun.kunaicode.exception.BusinessException;
import com.ikun.kunaicode.exception.ErrorCode;
import com.ikun.kunaicode.exception.ThrowUtils;
import com.ikun.kunaicode.model.enums.CodeGenTypeEnum;

import java.io.File;
import java.nio.charset.StandardCharsets;

/**
 * 代码文件保存模板类
 * @param <T>
 */
public abstract class CodeFileSaverTemplate<T> {
    /**
     * 文件保存的根目录
     */
    private static final String FILE_SAVE_ROOT_DIR = AppConstant.CODE_OUTPUT_ROOT_DIR;

    /**
     * 模板方法：保存代码的标准流程
     * @param result 代码结果对象
     * @param appId 应用id
     * @return 保存目录
     */
    public final File saveCode(T result, Long appId) {
        // 1. 校验输入
        validateInput(result);
        // 2. 构建唯一目录
        String baseDirPath = buildUniqueDir(appId);
        // 3. 保存文件
        saveFiles(result, baseDirPath);
        // 4. 返回
        return new File(baseDirPath);
    }

    /**
     * 验证输入参数（可重写）
     * @param result
     */
    protected void validateInput(T result) {
        if (result == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "代码结果对象不能为空");
        }
    }

    /**
     * 构建文件的唯一目录：tmp/code_output/codeType_应用id
     * @param appId 应用id
     * @return 目录路径
     */
    protected final String buildUniqueDir(Long appId) {
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR);
        String codeType = getCodeType().getValue();
        // codeType_应用id
        String uniqueDirName = StrUtil.format("{}_{}", codeType, appId);
        // 文件夹目录：tmp/code_output/codeType_应用id
        String dirPath = FILE_SAVE_ROOT_DIR + File.separator + uniqueDirName;
        // 创建文件夹
        FileUtil.mkdir(dirPath);
        return dirPath;
    }

    /**
     * 保存单个文件
     */
    protected final void writeToFile(String dirPath, String fileName, String content) {
        if (StrUtil.isNotBlank(content)) {
            // 文件路径
            String filePath = dirPath + File.separator + fileName;
            FileUtil.writeString(content, filePath, StandardCharsets.UTF_8);
        }
    }

    /**
     * 获取代码生成类型
     * @return
     */
    protected abstract CodeGenTypeEnum getCodeType();

    /**
     * 保存代码到文件
     * @param result
     * @param baseDirPath
     */
    protected abstract void saveFiles(T result, String baseDirPath);
}
